package com.tjetc.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.tjetc.constant.RedisConstant;
import com.tjetc.domain.Alternate;
import com.tjetc.domain.Patient;
import com.tjetc.domain.Scheduling;
import com.tjetc.mapper.AlternateMapper;
import com.tjetc.mapper.PatientMapper;
import com.tjetc.mapper.SchedulingMapper;
import com.tjetc.util.DateUtil;
import com.tjetc.util.Db;
import com.tjetc.vo.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import com.tjetc.mapper.RankRecordMapper;
import com.tjetc.domain.RankRecord;
import com.tjetc.service.RankRecordService;
import org.springframework.transaction.annotation.Transactional;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Service
public class RankRecordServiceImpl implements RankRecordService{

    @Resource
    private RankRecordMapper rankRecordMapper;

    private final ConcurrentHashMap<String, Object> lockPool = new ConcurrentHashMap<>();

    @Autowired
    private SchedulingMapper schedulingMapper;
    @Autowired
    private AlternateMapper alternateMapper;
    @Autowired
    private PatientMapper patientMapper;

    @Override
    public int deleteByPrimaryKey(Integer id) {
        return rankRecordMapper.deleteByPrimaryKey(id);
    }

    @Override
    public int insert(RankRecord record) {
        return rankRecordMapper.insert(record);
    }

    @Override
    public int insertSelective(RankRecord record) {
        return rankRecordMapper.insertSelective(record);
    }

    @Override
    public RankRecord selectByPrimaryKey(Integer id) {
        return rankRecordMapper.selectByPrimaryKey(id);
    }

    @Override
    public int updateByPrimaryKeySelective(RankRecord record) {
        return rankRecordMapper.updateByPrimaryKeySelective(record);
    }

    @Override
    public int updateByPrimaryKey(RankRecord record) {
        return rankRecordMapper.updateByPrimaryKey(record);
    }

    @Override
    public Result getRankVos(Integer id) {
        List<RankVo> rankVos = rankRecordMapper.getRankVos(id);
        for (RankVo rankVo : rankVos) {
            String time = rankVo.getTime();
            Date date = DateUtil.stringToDate(time);
            if (date != null){
                if (date.getHours()>=0  && date.getHours()<=12){
                    rankVo.setTime(DateUtil.getDate(date) + "  上午");
                }else if (date.getHours()>=13){
                    rankVo.setTime(DateUtil.getDate(date) + "  下午");
                }
            }
            if (new Date().after(date)){
                rankVo.setShuangYue(true);
            }else {
                rankVo.setShuangYue(false);
            }
        }
        return Result.ok(rankVos);
    }
    @Override
    public Result getHospitalBuildingByPidAndHospitalName(Integer pid, String hospitalName,Integer scheduleId) {
        HospitalBuildingInfoVo info = rankRecordMapper.getHospitalBuildingWithRoom(pid, hospitalName,scheduleId);
        if (info == null) {
            return Result.fail("未找到相关挂号信息");
        }
        System.out.println("======="+info);
        return Result.ok(info);
    }

    @Override
    public Result getMyRankRecord(Integer pid, String hospitalName) {
        List<RankRecord> myRankRecord = rankRecordMapper.getMyRankRecord(pid, hospitalName);
        System.out.println("myRankRecord.length="+myRankRecord.size());
        return myRankRecord.size()>0?Result.ok(myRankRecord):Result.fail();
    }

    @Override
    public Result getCurrentcallnumber(Integer scheduleId) {
        RankRecord rankRecord = rankRecordMapper.selectMaxOrderByScheduleIdAndState(scheduleId);
        if (rankRecord == null){
            return Result.fail("未开始就诊");
        }
        return  Result.ok(rankRecord);
    }

    @Override
    @Transactional
    public Result rank(RankDTO rankDTO) {
        //查询是否预约过
        RankRecord record = rankRecordMapper.selectBySidAndPid(rankDTO.getScheduleId(),rankDTO.getPid());
        if (record != null){
            return Result.fail("你已经预约过了");
        }
        //查询该患者绑定的用户今年的爽约次数
        Integer count = rankRecordMapper.selectShuangYueNum(rankDTO.getPid());
        if (count >= 3){
            return Result.fail("您今年有三次爽约记录,无法继续挂号");
        }
        // 生成唯一锁ID
        String lockId = "lock:scheduleId:" + rankDTO.getScheduleId();
        // 获取排班记录专属锁
        Object lock = lockPool.computeIfAbsent(lockId, k -> new Object());
        synchronized (lock){
            Scheduling scheduling = schedulingMapper.selectByPrimaryKey(rankDTO.getScheduleId());
            if (scheduling == null || scheduling.getLeaveCount() <= 0 ){
                return Result.fail("已无余量");
            }
            //如果只剩一张票,将redis缓存的七日的状态删掉重新做缓存
            Db.jedis.del(RedisConstant.SCHEDULING_STATE + scheduling.getCid() + "-" + DateUtil.getDate(new Date()));
            //数据库原子操作
            int rows = schedulingMapper.updateSubCount(rankDTO.getScheduleId());
            if (rows == 0){
                return Result.fail("失败");
            }
            Patient patient = patientMapper.selectByPrimaryKey(rankDTO.getPid());
            RankRecord rankRecord = RankRecord.builder().pid(rankDTO.getPid()).scheduleId(rankDTO.getScheduleId()).time(new Date()).state(0).type(patient.getVisitType()).hid(rankDTO.getHid()).build();
            int row = rankRecordMapper.insert(rankRecord);
            return row == 1 ? Result.ok() : Result.fail("失败");
        }
    }

    @Override
    @Transactional
    public Result cancelRank(Integer rankId,Integer hid) {
        //查看是不是当天的预约
        RankRecord rankRecord = rankRecordMapper.selectByIdWithScheduling(rankId);
        if (rankRecord == null){
            return Result.fail("该预约不存在");
        }
        if (DateUtil.isSameDay(rankRecord.getScheduling().getDate(), new Date())){
            return Result.fail("当天的预约无法取消哦");
        }
        //查看该就诊人是否今天已经取消预约两次了
        Integer count = rankRecordMapper.selectCancelCountByDateAndPid(DateUtil.getDate(new Date()), rankRecord.getPid());
        if (count >= 2){
            return Result.fail("你今天已经取消预约两次了");
        }
        //取消预约
        int rows = rankRecordMapper.cancelRank(rankId);
        //如果取消预约成功,就从候补记录中取出一条加入到挂号记录中,并且根据时间排序,取出的是最早候补的一条,并把候补成功改成1
        if (rows == 1){
            // 生成唯一锁ID
            String lockId = "lock:scheduleId:" + rankRecord.getScheduleId();
            // 获取排班记录专属锁
            Object lock = lockPool.computeIfAbsent(lockId, k -> new Object());
            synchronized (lock) {
                //如果剩余数量大于0就不进行候补,并把剩余数量加一
                if (rankRecord.getScheduling().getLeaveCount() > 0) {
                    int row = schedulingMapper.updateAddCount(rankRecord.getScheduleId());
                    return row == 1 ? Result.ok() : Result.fail("失败");
                }
                //如果剩余数量为0就候补
                //先根据挂号记录查询候补表中的数据,且未成功
                List<Alternate> alternates = alternateMapper.selectBySid(rankRecord.getScheduling().getId());
                if (alternates.isEmpty()) {
                    //如果没有候补的就直接返回,并把剩余数量加一
                    int row = schedulingMapper.updateAddCount(rankRecord.getScheduleId());
                    //并且把redis中缓存的状态更新
                    Db.jedis.del(RedisConstant.SCHEDULING_STATE + rankRecord.getScheduling().getCid() + "-" + DateUtil.getDate(new Date()));
                    return row == 1 ? Result.ok() : Result.fail("失败");
                } else {
                    //候补,不改变剩余数量
                    Alternate alternate = alternates.get(0);
                    Patient patient = patientMapper.selectByPrimaryKey(alternate.getPid());
                    RankRecord record = RankRecord.builder().pid(alternate.getPid()).scheduleId(alternate.getScheduleId()).time(new Date()).state(0).type(patient.getVisitType()).hid(hid).build();
                    int row1 = rankRecordMapper.insert(record);
                    //修改成功状态
                    alternate.setIsSuccess(1);
                    int row2 = alternateMapper.updateByPrimaryKey(alternate);
                    return row1 + row2 == 2 ? Result.ok() :Result.fail("失败");
                }
            }
        }
        return Result.fail("失败");
    }
    @Override
    public Result getReportByRankId(Integer pid) {
        List<RankRecord> rankRecords = rankRecordMapper.getReportByRankId(pid);
        return Result.ok(rankRecords);
    }

    @Override
    public Result getRankCount(String hospitalName) {
        List<RankClinic> list=rankRecordMapper.getRankCount(hospitalName);
        return Result.ok(list);
    }


    @Override
    public Result getRankRecordsBySid(Integer sid) {
        List<RankRecord> rankRecords = rankRecordMapper.getRankRecordsBySid(sid);
        return Result.ok(rankRecords);
    }

    @Override
    @Transactional
    public Result jiaohao(Integer sid,Integer currentHao, Integer rid) {
        if (currentHao != 0){
            rankRecordMapper.updateOldHao(currentHao,sid);
        }
        rankRecordMapper.updateNewHaoByRid(rid);
        return Result.ok();
    }

    @Override
    public Result zhenduan(Integer rid) {
        Integer rows = rankRecordMapper.updateZhenDuanByRid(rid);
        return rows == 1 ? Result.ok() : Result.fail("失败");
    }

    @Override
    public Result getHaoAndZhen(Integer sid) {
        //查当前叫号和就诊的号
        RankRecord currentHaoRankRecord = rankRecordMapper.selectHao(sid);
        RankRecord currentZhenRankRecord = rankRecordMapper.selectZhen(sid);
        HaoAndZhenVo haoAndZhenVo = new HaoAndZhenVo();
        haoAndZhenVo.setHao(currentHaoRankRecord == null ? 0 : currentHaoRankRecord.getOrder());
        haoAndZhenVo.setZhen(currentZhenRankRecord == null ? 0 : currentZhenRankRecord.getOrder());
        return Result.ok(haoAndZhenVo);
    }

    @Override
    public Result jieshuzhenduan(Integer sid, Integer currentZhen, String result) {
        RankRecord rankRecord = rankRecordMapper.selectBySidAndOrder(sid, currentZhen);
        rankRecord.setResult(result);
        rankRecord.setState(1);
        int rows = rankRecordMapper.updateByPrimaryKey(rankRecord);
        return rows == 1 ? Result.ok() : Result.fail("结束失败");
    }
    public Result getByNameandPage(String idCard, String name, Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum,pageSize);

      List<RankRecord> list = rankRecordMapper.getByNameAndIdCard(idCard,name);
      if (list!= null&& list.size()>0){
          
            PageInfo<RankRecord> pageInfo=  new PageInfo<>(list);
            return Result.ok(pageInfo);


      }else {
          return Result.fail("没有查询到用户");
      }
    }

    @Override
    public Result payY(RankRecord rankRecord) {
        Integer rows = rankRecordMapper.selectMaxOrderByScheduleId(rankRecord.getScheduleId());
        if (rows == null){
            rankRecord.setOrder(1);
        }else {
            rankRecord.setOrder(rows+1);
        }
        rankRecord.setState(5);
        int i = rankRecordMapper.updateByPrimaryKeySelective(rankRecord);
        return i==1?Result.ok(rankRecord.getOrder()):Result.fail("支付失败");
    }

    @Override
    public Result getAllRankRecord() {
      List<RankRecord> list =  rankRecordMapper.getAll();
      return Result.ok(list);
    }

}
